﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Needle.DevToolkit.Services.UI;
using System.Windows.Forms;
using Needle.Utils.Extensions;
using Needle.DevToolkit.Services;
namespace Needle.DevToolkit.UI.Controls
{
    public partial class StatusUIManager : Component, IStatusUI
    {
        List<StatusInfo> _status;


        private ToolStripStatusLabel _statusLabel;
        public ToolStripStatusLabel StatusLabel
        {
            get { return _statusLabel; }
            set { _statusLabel = value; }
        }

        private ToolStripProgressBar _progressBar;
        public ToolStripProgressBar ProgressBar
        {
            get { return _progressBar; }
            set { _progressBar = value; }
        }

        private TimeSpan _timeout = 30.Seconds();
        public TimeSpan Timeout
        {
            get { return _timeout; }
            set
            {
                if (value < 1000.Milliseconds())
                    value = 1000.Milliseconds();
                _timeout = value;
            }
        }

        public StatusUIManager()
        {
            InitializeComponent();
            _status = new List<StatusInfo>();
        }

        public StatusUIManager(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
            _status = new List<StatusInfo>();
        }

        public object SetStatus(string text, int percent)
        {
            var info = new StatusInfo
            {
                Cookie = new object(),
                ExpiryDate = DateTime.Now.Add(Timeout),
                Percentage = percent,
                Text = text,
            };

            Push(info);
            return info.Cookie;
        }

        public void UpdateStatus(object cookie, string text, int percent)
        {
            var info = _status.Find(x => x.Cookie == cookie);

            if (info == null)
            {
                if (cookie == null)
                    throw new ArgumentNullException("cookie");
                info = new StatusInfo
                        {
                            Cookie = cookie,
                            ExpiryDate = DateTime.Now.Add(Timeout),
                            Percentage = percent,
                            Text = text,
                        };
            }
            else
            {
                _status.RemoveAll(x => x.Cookie == cookie);
                info.Text = text;
                info.Percentage = percent;
            }
            Push(info);
        }

        public void RemoveStatus(object cookie)
        {
            if (Peek() != null)
            {
                if (Peek().Cookie == cookie)
                    Pop();
                else
                    _status.RemoveAll(x => x.Cookie == cookie);
            }
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            var info = Peek();
            while (info != null && info.ExpiryDate < DateTime.Now)
            {
                Pop();
                info = Peek();
            }
        }

        private void UpdateUI(StatusInfo statusInfo)
        {
            if (statusInfo == null)
            {
                if (StatusLabel != null)
                    StatusLabel.Text = String.Empty;
                if (ProgressBar != null)
                    ProgressBar.Value = 0;
            }
            else
            {
                if (StatusLabel != null)
                    StatusLabel.Text = statusInfo.Text;
                if (ProgressBar != null)
                    ProgressBar.Value = statusInfo.Percentage;
            }
        }

        private void Push(StatusInfo info)
        {
            if (!timer1.Enabled)
                timer1.Start();

            _status.Add(info);
            UpdateUI(Peek());
        }

        private StatusInfo Peek()
        {
            if (_status.Count == 0)
                return null;
            var info = _status[_status.Count - 1];
            return info;
        }
        
        private StatusInfo Pop()
        {
            var info = Peek();
            if (_status.Count > 0)
            {
                _status.RemoveAt(_status.Count - 1);
                UpdateUI(Peek());
            }
            if (timer1.Enabled)
                timer1.Stop();
            return info;
        }

        private class StatusInfo
        {
            public object Cookie { get; set; }
            public string Text { get; set; }
            public int Percentage { get; set; }
            public DateTime ExpiryDate { get; set; }
        }

    }
}
